use chrono::{DateTime, Duration, Utc};
use jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation, decode, encode, errors::Error};
use serde::{Deserialize, Serialize};
use tracing::{debug, error};

#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
    pub sub: String,
    pub exp: i64,
    pub iat: i64,
}

impl Claims {
    pub fn new(sub: String, exp: DateTime<Utc>) -> Self {
        Self {
            sub,
            exp: exp.timestamp(),
            iat: Utc::now().timestamp(),
        }
    }
}

// 32字节安全密钥
pub const SECRET_KEY: &[u8] = b"030c8d02eea6e5e5219096bd076c41e58e955632d59beb7d44fa18e3fbccb0bd12345678901234";

// 生成JWT
pub fn generate_token(user_id: &str) -> Result<String, Error> {
    let claims = Claims::new(user_id.to_string(), Utc::now() + Duration::hours(1));
    let token = encode(
        &Header::default(),
        &claims,
        &EncodingKey::from_secret(SECRET_KEY),
    )?;
    debug!("Generated token: {}", token);
    Ok(token)
}

// 验证JWT
pub fn validate_token(token: &str) -> Result<Claims, Error> {
    debug!("Received token: {}", token);
    let mut validation = Validation::new(jsonwebtoken::Algorithm::HS256);
    validation.validate_exp = true;

    match decode::<Claims>(token, &DecodingKey::from_secret(SECRET_KEY), &validation) {
        Ok(data) => {
            debug!("Decoded claims: {:?}", data.claims);
            Ok(data.claims)
        }
        Err(e) => {
            error!("Token error: {:?}", e);
            Err(e)
        }
    }
} 

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generate_and_validate_token() {
        // 生成 token
        let user_id = "test_user";
        let token_result = generate_token(user_id);
        
        assert!(token_result.is_ok(), "Failed to generate token");

        let token = token_result.unwrap();

        // 验证 token
        let claims_result = validate_token(&token);

        assert!(claims_result.is_ok(), "Failed to validate token");
        
        let claims = claims_result.unwrap();
        
        // 检查 claims 中的信息是否正确
        assert_eq!(claims.sub, user_id.to_string());
    }

    #[test]
    fn test_invalid_token() {
        // 提供一个无效的 token
        let invalid_token = "invalid.token.here";

        let claims_result = validate_token(invalid_token);

        assert!(claims_result.is_err(), "Expected error for invalid token");
    }
}
